package com.jse.util.concurrent.new1.synchronizer;

import java.util.PriorityQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.junit.Test;

/**
 * 参考ArrayBlockingQueue已经实现了生产消费加锁功能
 * 
 * Condition取代notify和wait功能
 * @author zenghua233
 *
 */
public class ConditionTest {
	public static final int queueSize = 10;
	public PriorityQueue<Integer> queue = new PriorityQueue<>();
	public Lock lock = new ReentrantLock();
	private Condition notEmpty = lock.newCondition();
	private Condition notFull = lock.newCondition();
	
	@Test
	public void testCondition() throws InterruptedException {
		ExecutorService executor = Executors.newFixedThreadPool(4);
		
		for (int i = 0; i < 3; i++) {
			executor.execute(new Consumer());
		}
		executor.execute(new Producer());
	}
	
	class Producer implements Runnable {
		
		@Override
		public void run() {
			while (true) {
				try {
					lock.lock();
					while (queue.size() == queueSize) {
						try {
							System.out.println("producer生产已满等待");
							notFull.await();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
					
					queue.offer(1);
					System.out.println("produer通知消费");
					notEmpty.signal();
				} finally {
					lock.unlock();
				}
			}
		}
	}
	
	class Consumer implements Runnable {
		
		@Override
		public void run() {
			while (true) {
				try {
					lock.lock();
					while (queue.size() == 0) {
						try {
							System.out.println("Consumer消费完了等待");
							notEmpty.await();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
					
					queue.poll();
					System.out.println("Consumer通知生产");
					notFull.signalAll();
				} finally {
					lock.unlock();
				}
			}
		}
	}
}
